﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Rung.Net.Simple;
using Rung.Net.Events;
using System.Net;
using Rung.Net.Test.Utilities;
using Rung.Net.Enums;
using Rung.Net.Session;

namespace Rung.Net.Test
{
    public partial class SessionMainFormC : Form
    {
        public string ClientName { get; set; }
        SessionClient client = new SessionClient();
        // 刷新客户端列表
        System.Timers.Timer timer;
        List<ClientItemUI> clients;
        private object OBJ_Clients = new object();

        public SessionMainFormC()
        {
            InitializeComponent();
        }

        private void MainFormC_Load(object sender, EventArgs e)
        {
            client.OnConnected += new NetConnectedEventHandler(client_OnConnected);
            client.OnDisconnected += new NetDisconnectedEventHandler(client_OnDisconnected);
            client.OnReceived += new NetReceivedEventHandler<byte[]>(client_OnReceived);

            ddlAddresses.DataSource = NetUtility.GetLocalIpV4();

            this.clients = new List<ClientItemUI>();
            this.timer = new System.Timers.Timer(500);
            this.timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
            timer.Start();
        }

        private void SimpleMainFormC_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.client.Dispose();
        }

        void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (lbClients.IsDisposed == false && timer.Enabled && lbClients.IsHandleCreated)
            {
                lbClients.Invoke(new Action(() =>
                {
                    if (lbClients.IsDisposed == false && timer.Enabled && lbClients.IsHandleCreated)
                    {
                        object selectedItem = lbClients.SelectedItem;
                        lbClients.Items.Clear();

                        lock (OBJ_Clients)
                        {
                            foreach (var c in clients)
                            {
                                lbClients.Items.Add(c);
                            }
                        }

                        lbClients.SelectedItem = selectedItem;
                    }
                }));
            }
        }

        // 【连接】
        private void btnConnect_Click(object sender, EventArgs e)
        {
            string port = System.Configuration.ConfigurationManager.AppSettings["Cache_ServerPort"];
            client.TryConnect(((IPAddress)ddlAddresses.SelectedItem).ToString(), int.Parse(port));
        }

        // 【断开】
        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            client.Disconnect();
        }

        // 【发送(S)】
        private void btnSendToServer_Click(object sender, EventArgs e)
        {
            if (client.IsConnected)
            {
                string fullMsg = NetUtility.GetFullMessage(MessageType.TalkToServer, txbMessage.Text.Trim());
                client.Send(NetUtility.C(fullMsg));
            }
        }

        // 【发送(C)】
        private void btnSendToClient_Click(object sender, EventArgs e)
        {
            if (client.IsConnected)
            {
                // id1#id2#id3&哈哈
                List<Guid> ids = new List<Guid>();
                foreach (var item in lbClients.SelectedItems)
                {
                    ClientItemUI c = item as ClientItemUI;
                    if (c != null)
                    {
                        ids.Add(c.Id);
                    }
                }
                if (ids.Count > 0)
                {
                    string body = string.Format("{0}{1}{2}", 
                        string.Join(LevelSeperators.Level2.ToString(),ids.ToArray()), 
                        LevelSeperators.Level1, 
                        txbMessage.Text.Trim());
                    string fullMsg = NetUtility.GetFullMessage(MessageType.TalkToClient, body);
                    client.Send(NetUtility.C(fullMsg));
                }
            }
        }

        // 【广播消息】
        private void btnSendMsgEcho_Click(object sender, EventArgs e)
        {
            if (client.IsConnected)
            {
                string fullMsg = NetUtility.GetFullMessage(MessageType.EchoAllClientExceptSender, "小弟冒个泡~");
                client.Send(NetUtility.C(fullMsg));
            }
        }

        void client_OnReceived(object sender, NetReceivedEventArgs<byte[]> e)
        {
            string data = NetUtility.C(e.Data);

            string body;
            string[] bodyRaws;
            switch (NetUtility.GetMessageType(data))
            {
                case MessageType.Login:
                    bodyRaws = NetUtility.GetMessageBody(data).Split(LevelSeperators.Level1);
                    lock (OBJ_Clients)
                    {
                        Guid id = Guid.Parse(bodyRaws[0]);
                        string name = bodyRaws[1];

                        if (this.clients.Find(c => { return c.Id == id; }) == null)
                            this.clients.Add(new ClientItemUI { Id = id, Name = name });
                    }
                    break;
                case MessageType.Logout:
                    body = NetUtility.GetMessageBody(data);
                    lock (OBJ_Clients)
                    {
                        Guid id = Guid.Parse(body);
                        ClientItemUI client = this.clients.Find(c => { return c.Id == id; });
                        if (client != null)
                            this.clients.Remove(client);
                    }
                    break;
                case MessageType.GetAllOnlineClient:
                    lock (OBJ_Clients)
                    {
                        this.clients.Clear();
                        bodyRaws = NetUtility.GetMessageBody(data).Split(LevelSeperators.Level1);

                        foreach (var raw in bodyRaws)
                        {
                            try
                            {
                                string[] idName = raw.Split(LevelSeperators.Level2);
                                Guid id = Guid.Parse(idName[0]);
                                string name = idName[1];

                                if (this.clients.Find(c => { return c.Name == name; }) == null)
                                    this.clients.Add(new ClientItemUI { Id = id, Name = name });
                            }
                            catch (Exception ex)
                            {
                                write("【收】" + ex.Message + "\t\t\tOnReceived");
                            }
                        }
                    }
                    break;
                case MessageType.TalkToClient:
                    bodyRaws = NetUtility.GetMessageBody(data).Split(LevelSeperators.Level1);
                    ClientItemUI sayer = this.clients.Find(c => { return c.Id == Guid.Parse(bodyRaws[0]); });
                    if (sayer != null)
                        write(string.Format("{0}：{1}", sayer.Name, bodyRaws[1]));
                    else
                        write(string.Format("陌生人：{0}", bodyRaws[1]));
                    break;
                default:
                    write(string.Format("【收】{0}", data));
                    break;
            }
        }
        void client_OnDisconnected(object sender, NetDisconnectedEventArgs e)
        {
            string message = "【断】";
            switch (e.Reason)
            {
                case NetStoppedReason.Exception:
                    message += "异常。";
                    break;
                case NetStoppedReason.Manually:
                    message += "手动。";
                    break;
                case NetStoppedReason.Remote:
                    message += "远程。";
                    break;
                case NetStoppedReason.SessionEnd:
                    message += "会话结束。";
                    break;
            }
            write(message);

            this.clients.Clear();
        }
        void client_OnConnected(object sender, NetConnectedEventArgs e)
        {
            write("【连】");
            // 模拟登陆
            this.ClientName = this.Text;
            string data = NetUtility.GetFullMessage(MessageType.Login, this.ClientName);
            client.Send(NetUtility.C(data));
        }

        void write(string s)
        {
            if (!lbInfo.IsDisposed)
            {
                Invoke(new Action(delegate
                {
                    #region 当前计时
                    long tick = 0L;
                    tick = tick - tick / 1000000 * 1000000;
                    #endregion

                    lbInfo.Items.Add(string.Format("[{0}] {1}", tick, s));
                    lbInfo.SelectedIndex = lbInfo.Items.Count - 1;
                }));
            }
        }

        internal class ClientItemUI
        {
            internal Guid Id;
            internal string Name;

            public override string ToString()
            {
                return this.Name;
            }
        }
    }
}
